home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_02_01 / 2n01021a < prev    next >
Text File  |  1990-10-10  |  15KB  |  467 lines

  1. Listing 2.  Timer Package Source Code.
  2.  
  3.         TITLE   TIMER - STARLITE Timer System.
  4.  
  5. ;***    TIMER -- Lightweight Timer Package.
  6. ;
  7. ;1.     Functional Description.
  8. ;       This module of STARLITE contains all of the code
  9. ;       necessary to implement the timer object used inside
  10. ;       the system.
  11. ;
  12. ;       The system is implemented in a very straightforward
  13. ;       and fast way that also burns system memory pool.
  14. ;       It is an a priori assumption that these timers almost
  15. ;       never fire, they are usually set and reset very
  16. ;       frequently (thousands of times per second).
  17. ;
  18. ;       The basic implementation is that a block of memory
  19. ;       is allocated at initialization time, and that block
  20. ;       is used as an array of timer objects.  Exported handles
  21. ;       are offset addresses of the elements (relative to the
  22. ;       beginning of DOSDATA), since system pool is addressable
  23. ;       in DOSDATA.
  24. ;
  25. ;       Starts and stops are made very fast (in fact, single
  26. ;       instructions) while scans through the timer database
  27. ;       are actually fairly fast (at least, faster than a
  28. ;       linked list of them), although this is less important
  29. ;       since the timer database is scanned every 32ms
  30. ;       (basically, on a timer tick).
  31. ;
  32. ;       Allocations and deallocations also happen to be quick,
  33. ;       since the allocator just scans the array for a free
  34. ;       entry, and the deallocator just clears the "in use"
  35. ;       bit of an entry.
  36. ;
  37. ;2.     Modification History.
  38. ;       S. E. Jones     90/06/15.       Original for 1.0.
  39. ;
  40. ;3.     NOTICE.
  41. ;       This software is a derivative of the timer code
  42. ;       that is licensed as a part of General Software's
  43. ;       STARLITE architecture.  The code in this article
  44. ;       can be freely incorporated into programs without
  45. ;       licensing STARLITE architecture from General Software.
  46. ;
  47. ;4.     Build Environment.
  48. ;       MASM 5.10, no special switches.
  49.  
  50. ;       Here are some useful macros to define
  51. ;       procedures and call them.  They eliminate
  52. ;       the need to manually declare EXTRN's.
  53.  
  54. DefProc MACRO   name
  55.         PUBLIC  name
  56. name    PROC    NEAR
  57.         ENDM
  58.  
  59. EndProc MACRO   name
  60.         ret
  61.         ASSUME  NOTHING
  62. name    ENDP
  63.         ENDM
  64.  
  65. Pcall   MACRO   name
  66.         IF2
  67.         IFNDEF  name
  68.         EXTRN   name:NEAR
  69.         ENDIF
  70.         ENDIF
  71.         call    name
  72.         ENDM
  73.  
  74. longword        struc
  75. lo              dw      ?
  76. hi              dw      ?
  77. longword        ends
  78.  
  79. ;       Package constants.
  80.  
  81. MILLISECONDS_PER_TICK   = 55    ; time between ExpireTimer runs.
  82.  
  83. ;       Define a timer object.
  84.  
  85. TIMER           struc
  86. timer_timeout   dd      ?       ; absolute time of expiration.
  87. timer_rtn       dd      ?       ; address of routine to execute.
  88. timer_flags     dw      ?       ; conditions on this timer.
  89. timer_context   dw      ?       ; context value passed to routine.
  90. TIMER           ends
  91.  
  92. TIMER_FLAGS_ALLOCATED   = 0001h ; timer object is in use.
  93. TIMER_FLAGS_RUNNING     = 0002h ; timer is running.
  94.  
  95. TIMERCODE SEGMENT PARA PUBLIC 'CODE'
  96. TIMERCODE ENDS
  97.  
  98. CGROUP    GROUP TIMERCODE       ; add other code segs here.
  99.  
  100. TIMERDATA SEGMENT PARA PUBLIC 'DATA'
  101.  
  102. ;       The following statics are private to the package.
  103.  
  104. TimeCounter     dd      ?       ; milliseconds since power-on.
  105.  
  106. MAX_TIMERS      =       100     ; number of timers in system.
  107. StaticArray     db      MAX_TIMERS dup (type TIMER)
  108. TimerArray      dw      0       ; offset pointer to timer array.
  109.  
  110. TIMERDATA ENDS
  111.  
  112. DGROUP    GROUP TIMERDATA       ; add other data segs here.
  113.  
  114. TIMERCODE SEGMENT
  115.  
  116. ;***    InitializeTimerSystem - Initialize the Timer System.
  117. ;
  118. ;   FUNCTIONAL DESCRIPTION.
  119. ;       This routine is called by the application to
  120. ;       initialize the timer package.
  121. ;
  122. ;   ENTRY.
  123. ;       none.
  124. ;
  125. ;   EXIT.
  126. ;       none.
  127. ;
  128. ;   USES.
  129. ;       flags.
  130.  
  131.         ASSUME  CS:CGROUP, DS:NOTHING, ES:NOTHING, SS:NOTHING
  132. DefProc InitializeTimerSystem
  133.         push    ax
  134.         push    bx
  135.         push    cx
  136.         push    dx
  137.         push    si
  138.         push    di
  139.         push    ds
  140.         mov     ax, DGROUP
  141.         mov     ds, ax                  ; (DS) = DGROUP.
  142.         ASSUME  DS:DGROUP
  143.  
  144.         lea     di, CGROUP:StaticArray  ; (DI) = adr, database.
  145.         mov     TimerArray, di          ; save database address.
  146.  
  147. ;       Initialize timer database.
  148.  
  149.         mov     cx, MAX_TIMERS          ; (CX) = number of entries to reset.
  150. InitializeTimerSystem_Loop:
  151.         mov     timer_flags.[di], 0     ; reset this timer.
  152.         add     di, (SIZE TIMER)        ; (DI) = FWA, next timer.
  153.         loop    InitializeTimerSystem_Loop ; do the rest of 'em.
  154.  
  155. ;       Reset the current time up-counter.
  156.  
  157.         sub     ax, ax
  158.         mov     TimeCounter.lo, ax
  159.         mov     TimeCounter.hi, ax
  160.  
  161.         pop     ds
  162.         ASSUME  DS:NOTHING
  163.         pop     di
  164.         pop     si
  165.         pop     dx
  166.         pop     cx
  167.         pop     bx
  168.         pop     ax
  169. EndProc InitializeTimerSystem
  170.  
  171. ;***   ExpireTimers - Fire Any Expired Timers.
  172. ;
  173. ;   FUNCTIONAL DESCRIPTION.
  174. ;       This routine is called by interrupt 8 to expire
  175. ;       system timers.  Expired timers are called with
  176. ;       interrupts ENABLED and with a context in (BX).
  177. ;       All timer routines are called with FAR linkage,
  178. ;       so they must return with RETF.
  179. ;
  180. ;   ENTRY.
  181. ;       none.
  182. ;
  183. ;   EXIT.
  184. ;       none.
  185. ;
  186. ;   USES.
  187. ;       flags.
  188.  
  189.         ASSUME  CS:CGROUP, DS:NOTHING, ES:NOTHING, SS:NOTHING
  190. DefProc ExpireTimers, PUBLIC
  191.         push    ax
  192.         push    bx
  193.         push    cx
  194.         push    dx
  195.         push    si
  196.         push    di
  197.         push    ds
  198.         mov     ax, DGROUP
  199.         mov     ds, ax                  ; (DS) = DGROUP.
  200.         ASSUME  DS:DGROUP
  201.  
  202.         cli                             ; BEGIN CRITICAL SECTION.
  203.         add     TimeCounter.lo, MILLISECONDS_PER_TICK
  204.         adc     TimeCounter.hi, 0       ; do 32-bit update.
  205.         sti                             ; END CRITICAL SECTION.
  206.  
  207. ExpireTimers_Scan:
  208.         nop                             ; widen interrupt window.
  209.         nop
  210.         nop
  211.         mov     ax, DGROUP
  212.         mov     ds, ax                  ; (DS) = DGROUP.
  213.  
  214.         cli                             ; BEGIN CRITICAL SECTION.
  215.         mov     dx, TimeCounter.hi
  216.         mov     ax, TimeCounter.lo      ; (DX:AX) = current time.
  217.         mov     di, TimerArray          ; (DI) = FWA, 1st timer in system.
  218.         or      di, di                  ; is there a timer array?
  219.         jz      ExpireTimers_Exit       ; if not.
  220.         sub     di, (SIZE TIMER)        ; backup one for algorithm.
  221.         mov     cx, MAX_TIMERS          ; number of timers in system.
  222.  
  223. ExpireTimers_Loop:
  224.         dec     cx                      ; (CX) = one less timer to go.
  225.         jz      ExpireTimers_Exit       ; if there are no more, we're done.
  226.         add     di, (SIZE TIMER)        ; (DI) = FWA, next timer in system.
  227.  
  228.         test    timer_flags.[di], TIMER_FLAGS_ALLOCATED ; is the timer allocated?
  229.         jz      ExpireTimers_Loop       ; if not.
  230.         test    timer_flags.[di], TIMER_FLAGS_RUNNING ; is the timer running?
  231.         jz      ExpireTimers_Loop       ; if not.
  232.  
  233. ;       If the expiration time is greater than or equal to the current time,
  234. ;       then we call the timer routine and stop the timer.
  235.  
  236.         cmp     timer_timeout.hi.[di], dx ; is the timer's time > current time?
  237.         ja      ExpireTimers_Loop       ; if so.
  238.         jb      ExpireTimers_Expire     ; if expired.
  239.  
  240. ;       The most significant portions of the times match exactly.  Use the
  241. ;       low-order times to compare.
  242.  
  243.         cmp     timer_timeout.lo.[di], ax ; is the timer's time > current time?
  244.         ja      ExpireTimers_Loop       ; if so.
  245.  
  246. ;       The timer has expired.  Enable interrupts and call the routine.
  247.  
  248. ExpireTimers_Expire:
  249.         and     timer_flags.[di], NOT TIMER_FLAGS_RUNNING ; turn off running bit.
  250.         mov     timer_timeout.hi.[di], -1    ; ext